package com.example.lotterysystem.service.impl;

import com.example.lotterysystem.common.utils.JacksonUtil;
import com.example.lotterysystem.controller.param.DrawPrizeParam;
import com.example.lotterysystem.dao.dataobject.ErrorMessageDO;
import com.example.lotterysystem.dao.mapper.ErrorMessageMapper;
import com.example.lotterysystem.service.ErrorMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.example.lotterysystem.common.config.DirectRabbitConfig.EXCHANGE_NAME;
import static com.example.lotterysystem.common.config.DirectRabbitConfig.ROUTING;
import static com.example.lotterysystem.service.DrawPrizeService.MESSAGE_DATA;
import static com.example.lotterysystem.service.DrawPrizeService.MESSAGE_ID;

@Service
@Slf4j
public class ErrorMessageServiceImpl implements ErrorMessageService {
    @Autowired
    private ErrorMessageMapper errorMessageMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Scheduled(fixedRate = 3600000) // 每间隔 1h 执行一次
    @Override
    public void processErrorMessage() {
        // 判断是否有未处理的异常数据
        int errorMessageCount = errorMessageMapper.countProcessFalse();
        if (errorMessageCount <= 0) {
            return;
        }

        // 有异常数据，进行处理
        Map<String, List<ErrorMessageDO>> errorMessageMap = new HashMap<>();
        List<ErrorMessageDO> errorMessageDOList = errorMessageMapper.selectProcessedFalse();
        if (CollectionUtils.isEmpty(errorMessageDOList)) {
            return;
        }
        // 通过 messageId 聚合异常数据
        for(ErrorMessageDO errorMessageDO: errorMessageDOList) {
            String key = errorMessageDO.getMessageId();
            // 获取当前键对应的列表，如果不存在则新建一个
            List<ErrorMessageDO> list = errorMessageMap.getOrDefault(key, new ArrayList<>());
            // 将当前的 ErrorMessageDO 对象添加到列表中
            list.add(errorMessageDO);
            // 更新 map 中对应键的值
            errorMessageMap.put(key, list);
        }
        // 处理异常数据
        try {
            for (String key : errorMessageMap.keySet()) {
                // 构造请求
                List<ErrorMessageDO> errorMessageDOS = errorMessageMap.get(key);
                List<DrawPrizeParam.Winner> winnerList = errorMessageDOS
                        .stream()
                        .map(errorMessageDO -> {
                            DrawPrizeParam.Winner winner = new DrawPrizeParam.Winner();
                            winner.setUserId(errorMessageDO.getWinnerId());
                            winner.setUserName(errorMessageDO.getWinnerName());
                            return winner;
                        }).collect(Collectors.toList());
                DrawPrizeParam drawPrizeParam = new DrawPrizeParam();
                drawPrizeParam.setActivityId(errorMessageDOS.get(0).getActivityId());
                drawPrizeParam.setPrizeId(errorMessageDOS.get(0).getPrizeId());
                drawPrizeParam.setWinningTime(errorMessageDOS.get(0).getWinningTime());
                drawPrizeParam.setWinnerList(winnerList);
                Map<String, String> messageMap = new HashMap<>();
                String messageId = UUID.randomUUID().toString();
                String messageData = JacksonUtil.writeValueAsString(drawPrizeParam);
                messageMap.put(MESSAGE_ID, messageId);
                messageMap.put(MESSAGE_DATA, messageData);
                rabbitTemplate.convertAndSend(EXCHANGE_NAME, ROUTING, messageMap);
                log.info("processErrorMessage 向 mq 发送消息成功, map: {}", JacksonUtil.writeValueAsString(messageMap));
                // 将消息标记为已处理
                errorMessageMapper.batchUpdate(errorMessageDOS);
            }
        } catch (Exception e) {
            log.warn("消息处理异常：", e);
        }
    }
}
